package com.thd.springboot.project.codegenerator.service;

import com.thd.springboot.framework.generator.core.CodeGen;
import com.thd.springboot.framework.generator.core.dto.TemplateData;
import com.thd.springboot.framework.generator.core.tableutil.TableUtil;
import com.thd.springboot.framework.generator.core.tool.StringTemplate;
import com.thd.springboot.framework.utils.MyZipUtils;
import com.thd.springboot.framework.utils.UuidUtils;
import com.thd.springboot.project.codegenerator.dto.GeneratResultDto;
import com.thd.springboot.project.codegenerator.entity.GeneratorTemplateEntity;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CodeGenServiceImpl implements CodeGenService{
    @Autowired
    private CodeGen cgUtil;

    @Autowired
    private TableUtil tableUtil;

    @Autowired
    GeneratorTemplateService generatorTemplateService;

    @Autowired
    private TemplateData templateData;

    private Logger logger = LoggerFactory.getLogger(CodeGenServiceImpl.class);
    public TemplateData getTemplateData(String tableName) throws Exception{
        TemplateData thisTemplateData = new TemplateData();
        BeanUtils.copyProperties(thisTemplateData,templateData);
        thisTemplateData.setTable(tableUtil.loadTable(tableName));
        thisTemplateData.setDbType(templateData.getDbType().toLowerCase());

        thisTemplateData.getCoding().setBasicPackageName(StringTemplate.generatByTemplateStr(thisTemplateData.getCoding().getBasicPackageName(),thisTemplateData));
        thisTemplateData.getCoding().setControllerPackageName(StringTemplate.generatByTemplateStr(thisTemplateData.getCoding().getControllerPackageName(),thisTemplateData));
        thisTemplateData.getCoding().setEntityPackageName(StringTemplate.generatByTemplateStr(thisTemplateData.getCoding().getEntityPackageName(),thisTemplateData));
        thisTemplateData.getCoding().setMapperPackageName(StringTemplate.generatByTemplateStr(thisTemplateData.getCoding().getMapperPackageName(),thisTemplateData));
        thisTemplateData.getCoding().setServicePackageName(StringTemplate.generatByTemplateStr(thisTemplateData.getCoding().getServicePackageName(),thisTemplateData));
        return thisTemplateData;
    }

    public void createCode(List<String> ids, String tableName,TemplateData templateData,GenerateResultHandler generateResultHandler) throws Exception{
        String charset = "utf-8";




        for(String id : ids){

            GeneratorTemplateEntity entity = this.generatorTemplateService.queryById(id);

            // 生成文件名称
            String targetFileName = StringTemplate.generatByTemplateStr(entity.getFileNameDefault(),templateData);
            // 模板内容
            String templateStr = entity.getTemplateContent();
            // 根据模板生成的内容
            String fileContent = StringTemplate.generatByTemplateStr(templateStr,templateData);


            generateResultHandler.handler(fileContent,targetFileName);

        }

    }
    public String createCodeToZip(List<String> ids, List<String> tableNames) throws Exception{

        // 生成文件的根目录
        ApplicationHome h = new ApplicationHome(getClass());
        File jarF = h.getSource();
        String rootPath = jarF.getParentFile().toString();
        logger.info(" root path : {}" ,rootPath );
        String uuid = UuidUtils.uuid();

        // 生成根目录
        File targetFile = new File(rootPath+"/code_generator_result/" , uuid);
        targetFile.mkdirs();

        tableNames.stream().forEach( tableName -> {
            try{
                TemplateData thisTemplateData = getTemplateData(tableName);
                this.createCode(ids,tableName,thisTemplateData,(fileContent,targetFileName)->{
                    File f = new File(targetFile.getAbsolutePath(),targetFileName);
                    FileWriter fw = null;
                    try {
                        fw = new FileWriter(f);
                        fw.write(fileContent);//将字符串写入到指定的路径下的文件中
                        fw.close();
                    }catch(Exception e){
                        throw new RuntimeException(e);
                    }finally {
                        try{
                            if(null != fw){
                                fw.close();
                            }
                        }catch (Exception ex){
                            throw new RuntimeException(ex);
                        }
                    }
                });
            }catch(Exception e){
                throw new RuntimeException(e);
            }
        });

        MyZipUtils.toZipSingleExpand(targetFile.getAbsolutePath(),targetFile.getAbsolutePath()+".zip");
        return targetFile.getAbsolutePath()+".zip";
    }

    public Map<String,List<GeneratResultDto>> createCodeToData(List<String> ids, List<String> tableNames) throws Exception{
        Map<String,List<GeneratResultDto>> r = new HashMap<String,List<GeneratResultDto>>();
        tableNames.stream().forEach( tableName -> {

            List<GeneratResultDto> l = new ArrayList<GeneratResultDto>();
            try{
                TemplateData thisTemplateData = getTemplateData(tableName);
                this.createCode(ids,tableName,thisTemplateData,(fileContent,targetFileName)->{
                    l.add(GeneratResultDto.createInstane(targetFileName,fileContent));
                });
            }catch(Exception e){
                throw new RuntimeException(e);
            }

            r.put(tableName,l);
        });
        return r;
    }





    public String createCode(String id, String tableName) throws Exception{
        TemplateData templateData = this.getTemplateData(tableName);
        String content = this.createCode(id,tableName,templateData);
        return content;
    }
    public String createCode(String id, String tableName,TemplateData templateData) throws Exception{
        GeneratorTemplateEntity entity = this.generatorTemplateService.queryById(id);
        // 模板内容
        String templateStr = entity.getTemplateContent();
        // 根据模板生成的内容
        String fileContent = StringTemplate.generatByTemplateStr(templateStr,templateData);

        return fileContent;
    };
}
